import { LikeEntity } from './../../entities/like.entity';
import { UserEntity } from './../../../user/entities/user.entity';
import { CategoryEntity } from './../../../category/entities/category.entity';
import { mapToObj } from './../../../../../utils/map';
import { ICurrentUserType } from './../../../../../decorators/current.user';
import { PostsEntity } from './../../entities/posts.entity';
import { Injectable, BadRequestException, HttpException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, getConnection, Like, getManager, EntityManager } from 'typeorm';
import { CreatePostsInputDto } from '../../resolvers/posts/dto/create.posts.dto';
import { ModifyPostsInputDto } from '../../resolvers/posts/dto/modify.posts.dto';
import { PostsInputDto } from '../../resolvers/posts/dto/posts.dto';
import { PostListVo } from '../../resolvers/posts/vo/posts.vo';
import { PostsLikeInputDto } from '../../resolvers/posts/dto/post.like.dto';
import { PostsCollectInputDto } from '../../resolvers/posts/dto/post.collect.dto';
import { CollectEntity } from '../../entities/collect.entity';

@Injectable()
export class PostsService {
  constructor(
    @InjectRepository(PostsEntity)
    private readonly postsRepository: Repository<PostsEntity>,
    @InjectRepository(LikeEntity)
    private readonly likeRepository: Repository<LikeEntity>,
    @InjectRepository(CollectEntity)
    private readonly collectRepository: Repository<CollectEntity>,
  ) {}

  async createPost(
    userInfo: ICurrentUserType,
    createPostsInputDto: CreatePostsInputDto,
  ): Promise<string> {
    try {
      const { userId } = userInfo;
      const posts = this.postsRepository.create({ ...createPostsInputDto, userId });
      await this.postsRepository.save(posts);
      return '创建成功';
    } catch (e) {
      console.log(e);
      throw new BadRequestException('创建文章失败');
    }
  }

  async deletePostById(id: number, userInfo: ICurrentUserType): Promise<string> {
    // 先判断下你登录的不能去删除别人的文章
    const { userId } = userInfo;
    const isCurrentUserPost = await this.postsRepository.findOne({
      where: { id, userId },
      select: ['id'],
    });
    if (!isCurrentUserPost) {
      throw new BadRequestException('当前文章你无权删除');
    }
    // 这里使用软删除
    const {
      raw: { affectedRows },
    } = await this.postsRepository.softDelete(id);
    if (affectedRows) {
      return '删除成功';
    } else {
      return '删除失败';
    }
  }

  async modifyPostById(
    id: number,
    modifyPostsInputDto: ModifyPostsInputDto,
    userInfo: ICurrentUserType,
  ): Promise<string> {
    const { userId } = userInfo;
    const isCurrentUserPost = await this.postsRepository.findOne({
      where: { id, userId },
      select: ['id'],
    });
    if (!isCurrentUserPost) {
      throw new BadRequestException('当前文章你无权修改');
    }
    const {
      raw: { affectedRows },
    } = await this.postsRepository.update(id, { ...modifyPostsInputDto });
    if (affectedRows) {
      return '修改成功';
    } else {
      return '修改失败';
    }
  }


  async postsList(postsInputDto: PostsInputDto, userInfo?: ICurrentUserType): Promise<PostListVo> {
    const { pageSize = 10, pageNumber = 1, title } = postsInputDto || {};
    const userId = userInfo?.userId;
    const query = new Map();
    if (title) {
      query.set('title', Like(`%${title}%`));
    }
    const data = await getConnection()
      .createQueryBuilder(PostsEntity, 'posts')
      .select('posts.id', 'id')
      .addSelect('posts.title', 'title')
      .addSelect('posts.content', 'content')
      .addSelect('posts.categoryId', 'categoryId')
      .addSelect('posts.lookCount', 'lookCount')
      .addSelect('posts.likeCount', 'likeCount')
      .addSelect('posts.collectCount', 'collectCount')
      .addSelect('posts.createdAt', 'createdAt')
      .addSelect('posts.updatedAt', 'updatedAt')
      .addSelect(
        (qb) =>
          qb
            .select('name')
            .from(CategoryEntity, 'category')
            .where('posts.categoryId = category.id'),
        'categoryName',
      )
      .addSelect(
        (qb) =>
          qb
            .select('username')
            .from(UserEntity, 'user')
            .where('posts.userId = user.id'),
        'userName',
      )
      // 判断当前用户是否点赞，不返回null就表示当前用户点赞了
      .addSelect(
        (qb) =>
          qb
            .select('id')
            .from(LikeEntity, 'like')
            .where('like.userId =:userId and like.postId = posts.id', { userId }),
        'isLike',
      )
      .addSelect(
        (qb) =>
          qb
            .select('id')
            .from(CollectEntity, 'collect')
            .where('collect.userId =:userId and collect.postId = posts.id', { userId }),
        'isCollect',
      )
      .where(mapToObj(query))
      .skip((pageNumber - 1) * pageSize)
      .take(pageSize)
      .printSql()
      .getRawMany();
    const total = await getConnection()
      .createQueryBuilder(PostsEntity, 'posts')
      .where(mapToObj(query))
      .getCount();
    console.log(data, '查询数据');
    return {
      data,
      total,
    };
  }


  async postLike(
    userInfo: ICurrentUserType,
    postsLikeInputDto: PostsLikeInputDto,
  ): Promise<string> {
    const { userId } = userInfo;
    const { postId } = postsLikeInputDto;
    // 1、用户点赞的时候要给文章点赞数+1
    // 2.在要like表中记录下
    return getManager()
      .transaction(async (entityManager: EntityManager) => {
        const userLike = await this.likeRepository.findOne({ where: { userId, postId } });
        if (userLike) {
          // 如果是存在就取消点赞
          await entityManager.delete<LikeEntity>(LikeEntity, { userId, postId });
          await entityManager.decrement<PostsEntity>(PostsEntity, { id: postId }, 'likeCount', 1);
          return '取消点赞';
        } else {
          // 如果不存在就点赞
          const userLike = entityManager.create<LikeEntity>(LikeEntity, { userId, postId });
          await entityManager.save(LikeEntity, userLike);
          await entityManager.increment<PostsEntity>(PostsEntity, { id: postId }, 'likeCount', 1);
          return '点赞成功';
        }
      })
      .then((result: string) => {
        return result;
      })
      .catch((e: HttpException) => {
        console.log(e);
        return '点赞失败';
      });
  }

  async postCollect(
    userInfo: ICurrentUserType,
    postsCollectInputDto: PostsCollectInputDto,
  ): Promise<string> {
    const { userId } = userInfo;
    const { postId } = postsCollectInputDto;
    // 1、用户点赞的时候要给文章收藏+1
    // 2.在要collect表中记录下
    return getManager()
      .transaction(async (entityManager: EntityManager) => {
        const userCollect = await this.collectRepository.findOne({ where: { userId, postId } });
        if (userCollect) {
          // 如果是存在就取消收藏
          await entityManager.delete<CollectEntity>(CollectEntity, { userId, postId });
          await entityManager.decrement<PostsEntity>(
            PostsEntity,
            { id: postId },
            'collectCount',
            1,
          );
          return '取消收藏';
        } else {
          // 如果不存在就收藏
          const userCollect = entityManager.create<CollectEntity>(CollectEntity, {
            userId,
            postId,
          });
          await entityManager.save(CollectEntity, userCollect);
          await entityManager.increment<PostsEntity>(
            PostsEntity,
            { id: postId },
            'collectCount',
            1,
          );
          return '收藏成功';
        }
      })
      .then((result: string) => {
        return result;
      })
      .catch((e: HttpException) => {
        console.log(e);
        return '收藏失败';
      });
  }
}
